package com.junmo.oauth.module.system.entity;

import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Table(name = "sys_user")
@Entity
@DynamicUpdate // 实现动态更新
@DynamicInsert // 动态插入
@Accessors(chain = true)
@Data
public class SysUser implements UserDetails {
    @Id
    @GeneratedValue
    private Long userId;
    private String username;
    private String password;
    private String realName;
    private String phone;
    private String email;
    private Integer sex;
    private Integer locked;
    private Date lastTime;
    private Integer del_tag;
    @ManyToMany(targetEntity = SysRole.class, fetch=FetchType.EAGER)
// 配置关联表
    @JoinTable(name = "sys_user_role",
            joinColumns = { @JoinColumn(name = "user_id") },
            inverseJoinColumns = { @JoinColumn(name = "role_id") }
    )
    private Set<SysRole> roles;

    @Transient
    private  Set<GrantedAuthority> authorities;
    @Transient
    private  boolean accountNonExpired;
    @Transient
    private  boolean accountNonLocked;
    @Transient
    private  boolean credentialsNonExpired;
    @Transient
    private  boolean enabled;
    public SysUser(){ }
    public SysUser( Long userId,  String username, String password, List<String> authorities, boolean enabled ) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.authorities = mapToGrantedAuthorities(authorities);
        this.enabled = enabled;
    }
    public SysUser(Long userId, String username, String password, String authoritie,boolean enabled) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.authorities = mapToGrantedAuthorities(authoritie);
        this.enabled = enabled;
    }


    public SysUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }
    public SysUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        Assert.isTrue(username != null && !"".equals(username) && password != null, "Cannot pass null or empty values to constructor");
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
    }
    private Set<GrantedAuthority> mapToGrantedAuthorities(List<String> roles) {
        return Collections.unmodifiableSet( sortAuthorities(
                        roles.stream() .map(role -> new SimpleGrantedAuthority(role)) .collect(Collectors.toList())
                ));
    }
    private Set<GrantedAuthority> mapToGrantedAuthorities(String role) {
        return Collections.unmodifiableSet(  sortAuthorities(
                Arrays.asList(new SimpleGrantedAuthority(role))
        ));
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return this.accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled;
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet(new AuthorityComparator());
        Iterator var2 = authorities.iterator();

        while(var2.hasNext()) {
            GrantedAuthority grantedAuthority = (GrantedAuthority)var2.next();
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }

        return sortedAuthorities;
    }
    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
        private static final long serialVersionUID = 540L;

        private AuthorityComparator() {
        }

        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            if (g2.getAuthority() == null) {
                return -1;
            } else {
                return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority());
            }
        }
    }
}

